package sim;



import gnu.trove.TIntProcedure;

import java.awt.Dimension;
import java.awt.Toolkit;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.magnos.steer.Vector;








import ui.AntSimRenderer;
import util.Hilfsklasse;
import world.Ameisenhaufen;
import world.Futterhaufen;
import animal.Ameise;
import animal.Fresstier;
import animal.Kaefer;
import audio.AudioSystem;

import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;

import javazoom.jl.player.advanced.AdvancedPlayer;

/**
 * Ein Objekt dieser Klasse stellt eine Ameisensimulation dar. Teil der
 * Simulation sind Ameisen, Ameisenhaufen, Futterhaufen und Fresstiere.
 * 
 * @author Shkelqim Turkaj
 * @version 3.0
 * 
 */

public class AmeisenSimulation {

	public static int ANZAHL_AMEISEN = 5;

	private SimulationParameters simParam;
	private AntSimRenderer antsimrenderer;
	private AudioSystem audioSystem;
	private AdvancedPlayer player;
	private World world;
	private Fauna fauna;
	private Index gridIndex;
	private Index spatialIndex;
	//private long musikBeginn;

	/**
	 * Erzeugt die Ameisensimulation und zeigt ein Anwendungsfenster an, in
	 * welchem das Anzeigefeld zu sehen ist. Zu Beginn der Simulation befindet
	 * sich eine Ameise auf dem Feld.anzahl
	 */
	public AmeisenSimulation() {
		gridIndex = new Index(1000, 1000); 
		
		simParam = new SimulationParameters();
		antsimrenderer = new AntSimRenderer(simParam);
		Dimension screenSize = 	Toolkit.getDefaultToolkit().getScreenSize();
		
		LwjglApplicationConfiguration cfg = new LwjglApplicationConfiguration();
		cfg.title = "AntSIM OpenGL";
		//cfg.width = screenSize.width;
		//cfg.height = screenSize.height;
		cfg.width = 1024;
		cfg.height = 768;
		cfg.fullscreen = false;  
		cfg.forceExit = true;  
		cfg.foregroundFPS = 120;
		cfg.vSyncEnabled = false;
		
		new LwjglApplication(antsimrenderer, cfg);
		//new LwjglApplication(antsimrenderer, "AntSIM OpenGL", );
		audioSystem = new AudioSystem();
		audioSystem.loadSoundsFromFolder(new File("sounds"));
		//starte hintergrundmusik
		audioSystem.playSound("sounds/test1.ogg", 0.6f,true);
		

		spatialIndex = new Index(1000,1000);	
		world = new World(simParam,spatialIndex);
		world.init(this);
		fauna = new Fauna(simParam,spatialIndex);
		fauna.init(this);
		
		//new AudioPlayer("/sounds/test1.mp3").play();
		//setMusikBeginn(System.currentTimeMillis());
		//anzeigefeld = new Anzeigefeld();
		//anzeigefeld.zeigeInFenster();		
		antsimrenderer.showBorder(0, 0, simParam.getWorldWidth(), simParam.getWorldHeight());
		simuliere();		
	}

	/**
	 * Diese Methode ist fuer die Simulation zustaendig. Es werden jeweils die
	 * Berechnungen fuer einen Simulationsschritt durchgefuehrt, sowie die
	 * Anzeige aktalisiert. Zwischen zwei Simulationsschritten erfolgt stets
	 * eine Pause von 30 Millisekunden.
	 */
	public void simuliere() {
		while (true) {
			long t0= System.currentTimeMillis();
			fuehreEinenSimulationsschrittDurch();
			antsimrenderer.showSimSpeed(System.currentTimeMillis()-t0);
			Hilfsklasse.warte(simParam.getSimGeschwindigkeit());
		}
	}

	/**
	 * Diese Methode fuehrt einen Simulationsschritt durch.
	 */
	public void fuehreEinenSimulationsschrittDurch() {
		world.simulate(this);
		updateFoodSources();		
		fauna.simulate(this);	
	}		
	
	private void updateFoodSources(){		
		spatialIndex.updateFoodSourcesVisibility(world.getFutterhaufen(),
												(float)simParam.getWahrnehmbarFutter());
	}
	
	public SimulationParameters getSimulationParameters(){
		return this.simParam;
	}

//	public long getMusikBeginn() {
//		return musikBeginn;
//	}
//
//	public void setMusikBeginn(long musikBeginn) {
//		this.musikBeginn = musikBeginn;
//	}	


	/**
	 * Liefert das Anzeigefeld der Simulation.
	 * 
	 * @return das Anzeigefeld der Simulation
	 */
	//public Anzeigefeld getAnzeigefeld() {
	//	return anzeigefeld;
	//}

	/**
	 * Setzt das Anzeigefeld der Simulation.
	 * 
	 * @param anzeigefeld
	 *            Das Anzeigefeld der Simulation
	 */
	//public void setAnzeigefeld(Anzeigefeld anzeigefeld) {
	//	this.anzeigefeld = anzeigefeld;
	//}

	/**
	 * Wechselt den Hintergrund.
	 * 
	 * @param textur
	 *            Name der neuen Hintergrundtextur, welche sich im
	 *            "/grafiken/"-Ordner befinden sollte.
	 */
	//public void wechseleHintergrund(String textur) {
	//	anzeigefeld.setHintergrund("/grafiken/" + textur);
	//}

	/**
	 * Gibt die Liste mit Futterhaufen zur�ck.
	 * 
	 * @return Futterhaufenliste.
	 */
	public List<Futterhaufen> getAlleFutterhaufen() {
		return world.getFutterhaufen();
	}

	/**
	 * Gibt die Liste mit Ameisen zur�ck.
	 * 
	 * @return Liste aller zum aktuellen Zeitpunkt in der Simulation vorhandenen
	 *         Ameisen.
	 */
	public List<Ameise> getAlleAmeisen() {
		return fauna.getAmeisen();
	}

	/**
	 * Gibt die Liste mit Ameisen zur�ck.
	 * 
	 * @return Liste aller zum aktuellen Zeitpunkt in der Simulation vorhandenen
	 *         Ameisen.
	 */
	public List<Kaefer> getAlleKaefer() {
		return fauna.getKaefer();
	}

	public World getWorld(){
		return this.world;
	}
	
	/**
	 * Setzt einige Ameisen in die N�he eines Ameisenhaufens.
	 * 
	 * @param anzahl
	 *            Menge der Ameisen, die gesetzt werden sollen.
	 * @param grafik
	 *            Bild der Ameise (Art).
	 * @param ameisenhaufen
	 *            Ameisenhaufen, dem die Ameise zugeordnet werden soll.
	 */
	public void setAmeisen(int anzahl, String grafik,
			Ameisenhaufen ameisenhaufen) {
		for (int i = 0; i < ANZAHL_AMEISEN; i++) {
			Ameise ameise = new Ameise();
			ameise.setGrafik(grafik);
			ameise.setX(ameisenhaufen.getX());
			ameise.setY(ameisenhaufen.getY());
			ameisenhaufen.setGrafikAmeise(grafik);
			ameise.setAmeisenhaufen(ameisenhaufen);
			//ameisenliste.add(ameise);
			//anzeigefeld.setzeAmeise(ameise);
			antsimrenderer.addObjectToRender(ameise);
		}
	}

	
	/**
	 * @return the alleFresstiere
	 */
	public List<Fresstier> getAlleFresstiere() {
		return fauna.getFresstiere();
	}
	
	public AntSimRenderer getAntSimRenderer(){
		return antsimrenderer;
	}
	
	public AudioSystem getAudioSystem(){
		return audioSystem;
	}
}